"""

Copyright 2009 Michael Seiler
Rutgers University
miseiler@gmail.com

This file is part of ConsensusCluster.

ConsensusCluster is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

ConsensusCluster is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with ConsensusCluster.  If not, see <http://www.gnu.org/licenses/>.


"""

import logging

from ioutils import new_filename

def configure_logging(logname):
    """Open one logfile at a time for writing"""

    logfile = new_filename(logname, 'log', '.log')

    file_handler = logging.FileHandler(logfile, "a")    #Output log to logfile
    
    for handler in logging.root.handlers:
        handler.close()
        logging.root.removeHandler(handler)

    logging.root.addHandler(file_handler)
    logging.root.setLevel(logging.INFO)


class ConsoleDisplay(object):
    """
    
    ConsoleDisplay

        Usage:
            
            console = ConsoleDisplay(log, logname, tview)

                log     - Boolean variable.  If True, logging is enabled.
                          Note that attempting to change the current logfile via new_logfile
                          will make this True.

                logname - Name of new logfile.  .log suffix will be appended.  Optional.

        Properties:

            logging_enabled - The current boolean logging state.


        Colouring only works on linux consoles for now. Patches welcome.

    """
    
    def announce_wrap(self, announcement, f, *args, **kwds):
        """
        
        Usage:

            console.announce_wrap('Announcing function', function, *func_args, **func_kwds)

            This simple wrapper writes announcement, runs f, and outputs [OK] or [FAIL]
            depending on exception behaviour.

        This used to be a beautiful decorator, but I had no sensible way to pass console objects to it.

        """
            
        self.write(announcement)

        try:
            ret = f(*args, **kwds)
            self.success()
            return ret
        except:
            self.fail()
            raise
    
    def success(self):
        """Print success message"""

        print("".join([self.edge, self.success_colour, '[OK]', self.reset_colour]))

    def fail(self):
        """Print failure message"""

        print("".join([self.edge, self.fail_colour, '[FAIL]', self.reset_colour]))

    def except_to_console(self, message):
        """Writes message to console, shows failure, then raises an exception"""

        self.write(message)
        self.fail()
        raise ValueError, message

    def log(self, message, display=True):
        """Log message.  If display is True, message is also written to console"""
    
        if self.logging_enabled:
            logging.info(message)
            
            if display:
                self.write(message)

    def write(self, message):
        """Write message to console."""
        
        print(message)
    
    def new_logfile(self, logname=None):
        """Turn on logging (if it's off), and create a new logfile named "logname" """

        self.logging_enabled = True
        configure_logging(logname)

    def stop_logging(self):
        """Turn off logging, and close all open logfiles permanently"""

        self.logging_enabled = False

        for handler in logging.root.handlers:
            handler.close()
            logging.root.removeHandler(handler)

    def __init__(self, log=False, logname=None):
        
        self.logging_enabled = log

        self.edge = ' ' * 60 + '\t'             #Hack, should be replaced by real right-just formatting

        if log:
            configure_logging(logname)

        self.reset_colour = chr(27) + "[0m"     #Reset
        self.success_colour = chr(27) + "[32m"  #Green
        self.fail_colour = chr(27) + "[31m"     #Red
